use async_trait::async_trait;
use mf_derive::PState;
use mf_macro::{impl_plugin, mf_meta, mf_plugin};
use mf_model::node_definition::NodeTree;
use mf_state::error::StateResult;
use mf_state::{
    debug,
    plugin::{PluginTrait, StateField},
    resource::Resource,
    state::{State, StateConfig},
    transaction::Transaction,
};
use std::{collections::HashMap, sync::Arc};
async fn p1_append(
    _: &[Arc<Transaction>],
    _: &Arc<State>,
    new_state: &Arc<State>,
) -> anyhow::Result<Option<Transaction>> {
    let mut tr = new_state.tr();
    let doc = tr.doc();
    let root = doc.root().unwrap();
    let factory = tr.schema.factory();
    let n = factory.create_node("DW", None, None, vec![], None)?;
    let _ = tr.add_node(root.id.clone(), vec![NodeTree::from(n, vec![])]);
    Ok(Some(tr))
}

mf_plugin!(
    p1_plugin,
    metadata = mf_meta!(version = "1.0.0", description = "测试插件", author = "ModuForge Team", tags = ["validation", "security"]),
    append_transaction = p1_append
);

#[derive(Debug, PState)]
pub struct P1State1 {
    pub map: HashMap<String, String>,
}
#[derive(Debug)]
pub struct P1State2 {}
#[async_trait]
impl StateField for P1State2 {
    type Value = P1State1;

    async fn init(
        &self,
        config: &StateConfig,
        instance: &State,
    ) -> Arc<Self::Value> {
        let map: HashMap<String, String> = HashMap::from([("k".to_string(), "v".to_string())]);
        Arc::new(P1State1 { map })
    }

    /// 应用状态变更
    /// 根据事务内容更新插件状态
    async fn apply(
        &self,
        tr: &Transaction,
        value: Arc<Self::Value>,
        old_state: &State,
        new_state: &State,
    ) -> Arc<Self::Value> {
        value
    }
}

async fn p2_append(
    trs: &[Arc<Transaction>],
    _: &Arc<State>,
    new_state: &Arc<State>,
) -> StateResult<Option<Transaction>> {
    let mut tr = new_state.tr();
    let size = tr.doc().size();
    debug!("P2Plugin开始节点个数：{}", tr.doc().size());
    let doc = tr.doc();
    let root = doc.root().unwrap();
    let factory = tr.schema.factory();
    let node = factory.create_node("DW", None, None, vec![], None)?;
    if size < 10 {
        let _ = tr.add_node(root.id.clone(), vec![NodeTree::from(node, vec![])]);
        debug!("P2Plugin节点个数：{}", tr.doc().size());
        return Ok(Some(tr));
    }
    Ok(None)
}
mf_plugin!(
    p2_plugin,
    metadata = mf_meta!(version = "1.0.0", description = "测试插件2", author = "ModuForge Team", tags = ["validation", "security"]),
    append_transaction = p2_append,
    state_field = P1State2 {}
);
